#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <tbb/parallel_reduce.h>
#include <tbb/blocked_range.h>
#include <tbb/task_scheduler_init.h>

#define NTHREAD 10 

double step=0.005;

class Integral
{

   double x_l;
   double x_r;
   double summI; 
   
   double func(double x)
   {
      double y = x_l+x*step+step/2;
      double res = (sqrt(fabs(y)))*step;
      return res;
   }
   
   public:
   
   double getI() const
   {
	return summI;
   }
    
   void operator () (const tbb::blocked_range<size_t>& R)
   {
      double res = 0;
      for (size_t i=R.begin(); i<R.end(); ++i)
        {
	   summI += func(i);
        }
   }
   
   void join(const Integral& i)
   {
     summI += i.summI;
   }   

   Integral( Integral& i, tbb::split ): x_l(i.x_l), x_r(i.x_r), summI(0) {}
   Integral(double _xl, double _xr): x_l(_xl),x_r(_xr),summI(0) {}

   

};


int main(int argc, char* argv[])
{
  /*
 * Входными параметрами являются границы интервала, на котором нужно вычислить интеграл.
 * Также можно задать точность вычисления (шаг).
 * Количество нитей выполнения константно и равно 10
 */
 
double x1,x2,res,x3;

if (argc <3) 
{
printf ("arguments  invalid \n");
exit(1);
}

if (argc >=4)
{
     step = atof(argv[3]);
}
else step = 0.000001;


printf("start integral tbb  y=sqrt(abs(x)) \n");

x1=atof(argv[1]);
x2=atof(argv[2]);
if (x1>x2)
{
  x3=x1;
  x1=x2;
  x2=x3;
}


size_t n = (x2-x1)/step;

   printf("Qulity step: %d \n", n);
   tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred);
   init.initialize(NTHREAD);
   Integral sI(x1,x2);
   tbb::parallel_reduce (tbb::blocked_range<size_t>(0,n,NTHREAD), sI);
   init.terminate();
   res = sI.getI();   
   printf("result: %g \n", res);
   return 0;	
}

